# LuckPay Web Manage System
#
# Copyright (c) 2016 Lucky Byte, Inc.
#
express = require 'express'
pgsql   = require 'pg'
uuid    = require 'uuid'
crypto  = require 'crypto'
router = express.Router()
module.exports = router

# 用户列表
router.all '/', (req, res, next) ->
    await pgsql.connect settings.pgsql_url, defer err, client, done
    if err then done(client); return next(err)

    where_clause = "(
        u.realname like $1 or u.loginname like $1 or
        u.email like $1 or u.mobile like $1 or u.address like $1 or
        u.notes like $1
    )"
    where_clause += " and u.deleted = false"

    role = req.body.role or req.query.role
    if role and role.length > 0
        where_clause += " and u.role = '#{role}'"
        res.locals.role = role

    dept = req.body.dept or req.query.dept
    if dept and dept.length > 0
        where_clause += " and u.dept = '#{dept}'"
        res.locals.dept = dept

    # 查询所有角色，用于填充查询条件
    await client.query \
        "select * from web_roles", defer err, result
    if err then done(client); return next(err)
    res.locals.roles = result.rows

    # 查询记录总数
    await client.query \
        "select count(*) as count from web_users as u
            where #{ where_clause }",
        ['%' + res.locals.keyword + '%'], defer err, result
    if err then done(client); return next(err)
    res.locals.total = result.rows[0].count

    # 查询当前页面中显示的记录
    await client.query \
        "select u.*, r.name as role_name, r.root as role_root
            from web_users as u left join web_roles as r on r.uuid = u.role
            where #{ where_clause }
            order by serial offset $2::int limit $3::int",
        ['%' + res.locals.keyword + '%',
         res.locals.offset, res.locals.page_rows], defer err, result
    if err then done(client); return next(err)
    done()
    res.render 'users/index', records : result.rows


# 新增用户界面
router.get '/new', (req, res, next) ->
    res.locals.breadcrumbs.push 'title': '新增用户'

    await pgsql.connect settings.pgsql_url, defer err, client, done
    if err then done(client); return next(err)

    # 查询所有角色填充角色下拉框
    await client.query "select * from web_roles", defer err, result
    if err then done(client); return next(err)
    done()
    res.locals.roles = result.rows
    res.render 'users/new', record : {}


# 新增用户请求
router.post '/new', (req, res, next) ->
    for k in ['loginname', 'password', 'realname', 'role']
        return next(new Error("请求缺少参数[#{k}]")) if not req.body[k]

    await pgsql.connect settings.pgsql_url, defer err, client, done
    if err then done(client); next(err)

    user_uuid = uuid.v4()
    sha1 = crypto.createHash 'sha1'
    sha1.update(user_uuid)
    password = sha1.update(req.body.password).digest('hex')

    await client.query \
        "insert into web_users (
            ctime, uuid, loginname, password, role, realname, dept,
            birthday, gender, email, mobile, address,
            lock_enable, view_keys, view_trinfo, remove_notify,
            shortcuts, disabled, notes
        ) values (
            CURRENT_TIMESTAMP,
            $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12,
            $13, $14, $15, $16, $17, $18
        )", [
            user_uuid,
            req.body.loginname,
            password,
            req.body.role,
            req.body.realname,
            parseInt(req.body.dept),
            req.body.birthday || '1900-01-01',
            req.body.gender,
            req.body.email,
            req.body.mobile,
            req.body.address,
            req.body.lock_enable is 'on',
            req.body.view_keys is 'on',
            req.body.view_trinfo is 'on',
            req.body.remove_notify is 'on',
            req.body.shortcuts,
            false,
            req.body.notes,
        ], defer err, result
    if err then done(client); return next(err)
    done()
    res.redirect '/users'


# 修改用户界面
router.get '/edit/:id', (req, res, next) ->
    res.locals.breadcrumbs.push 'title': '修改用户信息'

    await pgsql.connect settings.pgsql_url, defer err, client, done
    if err then done(client); return next(err)

    # 查询所有角色填充角色下拉框
    await client.query \
        "select * from web_roles", defer err, result
    if err then done(client); return next(err)
    res.locals.roles = result.rows

    await client.query \
        "select * from web_users
            where serial = $1::int or uuid = $2::char", [
            parseInt(req.params.id) or 0,
            req.params.id
        ], defer err, result
    if err then done(client); return next(err)
    done()
    if result.rows.length != 1
        return next(new Error("查无此用户记录[#{req.params.id}]"))

    record = result.rows[0]
    record.shortcuts = JSON.stringify record.shortcuts
    res.render 'users/edit', record: record


# 修改用户信息
router.post '/edit', (req, res, next) ->
    for k in ['serial', 'uuid', 'loginname', 'realname', 'role']
        return next(new Error("请求缺少参数[#{k}]")) if not req.body[k]

    await pgsql.connect settings.pgsql_url, defer err, client, done
    if err then done(client); return next(err)

    await client.query \
        "select role, view_keys, view_trinfo from web_users
            where serial = $1 and uuid = $2", [
            req.body.serial, req.body.uuid,
        ], defer err, result
    if err then done(client); return next(err)
    if result.rows.length == 0
        done()
        return next(new Error('未找到原始记录'))

    # 保存原始权限
    role = result.rows[0].role
    view_keys   = result.rows[0].view_keys or false
    view_trinfo = result.rows[0].view_trinfo or false
    remove_notify = result.rows[0].remove_notify or false

    new_view_keys   = req.body.view_keys is 'on'
    new_view_trinfo = req.body.view_trinfo is 'on'
    new_remove_notify = req.body.remove_notify is 'on'

    await client.query \
        "update web_users set
            loginname = $1, role = $2, realname = $3, dept = $4,
            birthday = $5, gender = $6, email = $7, mobile = $8,
            address = $9,
            lock_enable = $10,
            view_keys = $11, view_trinfo = $12,
            remove_notify = $13,
            shortcuts = $14, notes = $15
        where
            serial = $16 and uuid = $17", [
            req.body.loginname,
            req.body.role,
            req.body.realname,
            parseInt(req.body.dept),
            req.body.birthday || '1900-01-01',
            req.body.gender,
            req.body.email,
            req.body.mobile,
            req.body.address,
            req.body.lock_enable is 'on',
            new_view_keys,
            new_view_trinfo,
            new_remove_notify,
            req.body.shortcuts,
            req.body.notes,
            req.body.serial,
            req.body.uuid,
        ], defer err, result
    if err then done(client); return next(err)

    # 如果密码修改了的话，继续更新密码
    password = if req.body.password then req.body.password else ''
    if password.length > 0
        sha1 = crypto.createHash 'sha1'
        sha1.update(req.body.uuid)
        password = sha1.update(password).digest('hex')
        await client.query \
            "update web_users set password = $1
                where serial = $2 and uuid = $3", [
                password, req.body.serial, req.body.uuid,
            ], defer err, result
        if err then done(client); return next(err)

    # 如果权限修改了，则强制退出此用户的登录
    if (
        role != req.body.role or
        view_keys != new_view_keys or
        view_trinfo != new_view_trinfo or
        remove_notify != new_remove_notify
        )
        await client.query "delete from web_session as s
            where s.sess#>>'{userinfo, uuid}' = $1", [
                req.body.uuid,
            ], defer err, result
        if err then done(client); return next(err)
        done()
        if req.session.userinfo.uuid is req.body.uuid
            req.session.userinfo = null
        return res.redirect '/'

    done()

    # 清除用户 session 中的快捷菜单
    req.session.shortcuts = null

    # 实时更新登录用户的显示名称
    if req.body.uuid == req.session.userinfo.uuid
        req.session.userinfo.realname = req.body.realname

    req.session.save (err) ->
        res.redirect '/users'


# 禁用
router.post '/disable', (req, res, next) ->
    res.type('json')
    for k in ['serial', 'uuid', 'disabled']
        return next(new Error("请求缺少参数[#{k}]")) if not req.body[k]

    if req.body.uuid == req.session.userinfo.uuid
        return next(new Error('出于安全考虑，您不可以禁用自己的帐号'))

    await pgsql.connect settings.pgsql_url, defer err, client, done
    if err then done(client); return next(err)

    await client.query \
        "update web_users set disabled = $1, failed_cnt = 0, unlock_time = null
            where serial = $2 and uuid = $3", [
            req.body.disabled,
            req.body.serial, req.body.uuid,
        ], defer err, result
    if err then done(client); return next(err)
    done()
    res.json succ: true, redirect: '/users'


# 删除用户
router.post '/delete', (req, res, next) ->
    res.type('json')
    for k in ['serial', 'uuid']
        return next(new Error("请求缺少参数[#{k}]")) if not req.body[k]

    if req.body.uuid == req.session.userinfo.uuid
        return next(new Error('出于安全考虑，您不可以删除自己的帐号'))

    await pgsql.connect settings.pgsql_url, defer err, client, done
    if err then done(client); return next(err)

    # 先尝试删除，如果没有外键引用，则删除之，否则修改其 deleted 状态
    await client.query \
        "delete from web_users where serial = $1 and uuid = $2", [
            req.body.serial, req.body.uuid,
        ], defer err, result
    if not err
        done()
        return res.json succ: true, redirect: '/users'

    await client.query "update web_users set
            deleted = true, deleted_no = max(deleted_no) + 1
        where serial = $1 and uuid = $2", [
            req.body.serial, req.body.uuid,
        ], defer err, result
    if err then done(client); return next(err)
    done()
    res.json succ: true, redirect: '/users'
